Pinecone のベクトルデータベースをエミュレートできる Pinecone Local を試してみた
こんにちは!AWS 事業本部コンサルティング部のたかくに(@takakuni_)です。
ローカルで Pinecone のベクトルデータベースをエミュレートできる、 Pinecone Local というものが登場しました。
開発で役に立ちそうです。さっそく試してみましょう。
Pinecone Local
Pinecone Local は Docker イメージとして利用できる、 Pinecone Vector Database のエミュレーターです。
ローカルまたは CI/CD 環境にコンテナイメージを落としてきて利用します。
docker run -d \
--name pinecone-local \
-e PORT=5081 \
-e PINECONE_HOST=localhost
-p 5081-6000:5081-6000 \
--platform linux/amd64 \
ghcr.io/pinecone-io/pinecone-local:latest
Pinecone Local はインデックスあり、インデックスなしの 2 種類のコンテナイメージを提供しています。
すぐに試したい方向けにはインデックス有り、テストやインデックスを自分で管理したい場合はインデックス無しと使い分けが推奨されています。
- Start Pinecone Local
You can configure Pinecone Local to start with or without indexes.
- Starting with indexes is recommended for getting started with Pinecone Database or quickly experimenting with reading and writing data. This approach use the pinecone-index Docker image.
- Starting without indexes is recommended for testing your production app or creating and managing indexes. This approach uses the pinecone-local Docker image.
今回利用したコードは以下のとおりです。
インデックス有り
まずはインデックス有りのコンテナを試してみます。いくつかパラメーターを指定するようです。
PORT
: ポート番号INDEX_TYPE
: インデックスタイプ(serverless または pod を指定)DIMENSION
: 次元数METRIC
: 類似度を計算するためのメトリクス(cosine, euclidean, dotproduct のどれかを指定)
- PORT: Specify the port number for the index to listen on.
- INDEX_TYPE: Specify the type of Pinecone index to create. Accepted values: serverless or pod.
- DIMENSION: Specify the dimension of vectors you will store in the index.
- METRIC: Specify the distance metric for calculating the similarity between vectors in the index. Accepted values: cosine, euclidean, or dotproduct.
Docker Compose から立ち上げてみましょう。
services:
index1:
image: ghcr.io/pinecone-io/pinecone-index:latest
environment:
PORT: 5081
INDEX_TYPE: serverless
DIMENSION: 1024
METRIC: cosine
ports:
- '5081:5081'
platform: linux/arm64
おっと怒られてしまいました。 ARM は対応していないみたいです。
takakuni@ pinecone-local-with-index % docker compose up -d
[+] Running 1/2
⠸ index1 [⣿] 2.222MB / 2.222MB Pulling 20.4s
✔ 593b926fe099 Pull complete 4.8s
image with reference ghcr.io/pinecone-io/pinecone-index:latest was found but does not match the specified platform: wanted linux/arm64, actual: linux/amd64
amd64
で docker-compose を動かしてみます。
services:
index1:
image: ghcr.io/pinecone-io/pinecone-index:latest
environment:
PORT: 5081
INDEX_TYPE: serverless
DIMENSION: 1024
METRIC: cosine
ports:
- '5081:5081'
+ platform: linux/amd64
上手く動きましたね。
takakuni:~/environment $ docker compose up -d
[+] Running 2/2
✔ index1 Pulled 1.5s
✔ 593b926fe099 Pull complete 0.6s
[+] Running 2/2
✔ Network environment_default Created 0.1s
✔ Container environment-index1-1 Started
インデックス無し
インデックス無しの方も試してみましょう。5082 ポートもデータの登録で利用するため大きめに開けます。
services:
index1:
image: ghcr.io/pinecone-io/pinecone-local:latest
environment:
PORT: 5081
PINECONE_HOST: localhost
ports:
- '5081-6000:5081-6000'
platform: linux/amd64
上手く動いていますね。
takakuni:~/environment $ docker compose up -d
[+] Running 2/2
✔ index1 Pulled 1.6s
✔ 3422d8f5b1d5 Pull complete 0.7s
[+] Running 2/2
✔ Network environment_default Created 0.1s
✔ Container environment-index1-1 Started
PineCone SDK でいくつか操作をしてみましょう。
from pinecone.grpc import PineconeGRPC
pc = PineconeGRPC(api_key="pclocal", host="http://localhost:5081")
result = pc.list_indexes()
print(result)
空のリストが返ってきました。
takakuni:~/environment $ python app.py
[]
インデックスでも作ってみましょう。
from pinecone.grpc import PineconeGRPC
from pinecone import ServerlessSpec
pc = PineconeGRPC(api_key="pclocal", host="http://localhost:5081")
index_name = "pinecone-local-index"
if not pc.has_index(index_name):
pc.create_index(
name=index_name,
dimension=1024,
metric='cosine',
spec=ServerlessSpec(
cloud="aws",
region="us-east-1"
)
)
result = pc.list_indexes()
print(result)
上手く作成できていますね。楽にローカルでテストできるのは嬉しいですね。
takakuni:~/environment $ python create_index.py
[{
"name": "pinecone-local-index",
"dimension": 1024,
"metric": "cosine",
"host": "localhost:5082",
"spec": {
"serverless": {
"cloud": "aws",
"region": "us-east-1"
}
},
"status": {
"ready": true,
"state": "Ready"
},
"deletion_protection": "disabled"
}]
埋め込み処理をしてみましょう。 GRPCClientConfig
で TLS を無効にするのがポイントです。
import boto3
import json
from pinecone.grpc import PineconeGRPC, GRPCClientConfig
pc = PineconeGRPC(api_key="pclocal", host="http://localhost:5081")
client = boto3.client("bedrock-runtime", region_name="us-east-1")
# 各種設定
model_id = "amazon.titan-embed-text-v2:0"
index_name = "pinecone-local-index"
input_text = "Please recommend books with a theme similar to the movie 'Inception'."
native_request = {"inputText": input_text}
# エンべディングの実行
request = json.dumps(native_request)
response = client.invoke_model(modelId=model_id, body=request)
request_id = response["ResponseMetadata"]["RequestId"]
model_response = json.loads(response["body"].read())
embedding = model_response["embedding"]
# ベクトルデータベースへの保管
host = pc.describe_index(index_name).host
index = pc.Index(host=host, grpc_config=GRPCClientConfig(secure=False))
result = index.upsert(
vectors=[
{
"id": request_id,
"values": embedding,
"metadata": {"text": input_text}
}
]
)
print(result)
一件登録できたと確認できました。
takakuni:~/environment $ python embeddings.py
upserted_count: 1
最後にデータを取得してみましょう。
from pinecone.grpc import PineconeGRPC, GRPCClientConfig
pc = PineconeGRPC(api_key="pclocal", host="http://localhost:5081")
index_name = "pinecone-local-index"
host = pc.describe_index(index_name).host
index = pc.Index(host=host, grpc_config=GRPCClientConfig(secure=False))
for ids in index.list():
print(index.fetch(ids))
values
の値は抜粋しますが、ベクトルデータが json 形式で取得できました。
{
"namespace": "",
"usage": {
"read_units": 0
},
"vectors": {
"b8b2d952-219f-418a-941b-73668ee29a8e": {
"id": "b8b2d952-219f-418a-941b-73668ee29a8e",
"metadata": {
"text": "'Please ''recommend ''books ''with ''a ''theme ''similar ''to ''the ''movie ''Inception'."
},
"sparse_values": { "indices": [], "values": [] },
"values": [-0.024926797]
}
}
}
まとめ
以上、「ローカルでベクトルデータベースがテストできる Pinecone Local を試してみる」でした。
エンべディングまでアプリで賄うケースで、開発スピードが向上しそうな気がしました。
このブログがどなたかの参考になれば幸いです。
AWS 事業本部コンサルティング部のたかくに(@takakuni_)でした!